package edu.mcw.rgd.clinminer.domain;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PersistenceContext;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.activerecord.RooJpaActiveRecord;
import org.springframework.roo.addon.tostring.RooToString;

import edu.mcw.rgd.clinminer.domain.common.EvidenceScoreUtils;
import edu.mcw.rgd.clinminer.domain.common.Persistable;
import edu.mcw.rgd.clinminer.domain.common.Recordable;

@RooJavaBean
@RooToString
@RooJpaActiveRecord
@Table(name = "MEDICATION")
public class Medication implements Recordable, Persistable {
	@Id
	@GeneratedValue(generator = "Medication_IDs_Seq")
	@SequenceGenerator(name = "Medication_IDs_Seq", sequenceName = "Medication_IDs_Seq", allocationSize = 1)
	@Column(name = "medication_id")
	private Long id;

	@ManyToOne
	@NotNull(message = "Participant cannot be empty")
	@JoinColumn(name = "participant")
	private Participant participant;

	@Column(name = "daily_dosage")
	private String dailyDosage;

	@Column(name = "dose_form")
	private String doseForm;

	@Column(name = "days")
	private String days;

	//
	// Recordable
	//

	@NotEmpty(message = "Annotated text cannot be empty")
	@Size(max = 4000, message = "Annotated text cannot be longer than 4000 characters")
	@Column(name = "annotated_text")
	private String annotatedText;

	@NotEmpty(message = "Document source cannot be empty")
	@Column(name = "document_source")
	private String documentSource;

	@Past(message = "Document date has to be in the past")
	@Temporal(TemporalType.TIMESTAMP)
	@DateTimeFormat(style = "S-")
	@Column(name = "document_source_date")
	private Date documentSourceDate;

	@Past(message = "Event date has to be in the past")
	@Temporal(TemporalType.TIMESTAMP)
	@DateTimeFormat(style = "S-")
	@Column(name = "event_date")
	private Date eventDate;

	@Column(name = "exact_date")
	private Boolean exactDate = false;

	@Column(name = "direct_observation")
	private Boolean directObservation = false;

	@Pattern(regexp = "(\\d+)|(N\\d+)|()", message = "Not a valid SNOMED CT, RxNorm or NDF-RT id")
	// TODO
	@Column(name = "ontology_termid")
	private String ontologyTermID;

	@Column(name = "ontology_term_label")
	private String ontologyTermLabel;

	@Size(max = 4000, message = "Notes cannot be longer than 4000 characters")
	@Column(name = "notes")
	private String notes;

	@AssertTrue(message = "At least one date has to be provided!")
	@Transient
	private boolean isValid() {
		return (documentSourceDate != null || eventDate != null);
	}

	@Override
	@Transient
	public Date getSingleDate() {
		if (eventDate != null) {
			return eventDate;
		} else {
			return documentSourceDate;
		}
	}

	@Override
	@Transient
	public Integer getEvidenceScore() {
		return EvidenceScoreUtils.calculate(getDocumentSourceDate(),
				getEventDate(), getDirectObservation(), getExactDate());
	}

	@PersistenceContext(unitName = "persistenceUnit")
	transient EntityManager entityManager;
}
